<template>
    <div class="material-page">
        <span class="title">素材识别</span>
        <div class="fliter">
            <div class="filter-item">
                <span class="filter-label" style="font-size: 14px;min-width: 70px;">关键词：</span>
                <el-input v-model="filterParams.keyword" style="width: 200px;" placeholder="请输入关键词" clearable />
            </div>
            <div class="filter-item">
                <span class="filter-label" style="font-size: 14px;min-width: 70px;">地区：</span>
                <el-select v-model="filterParams.area" style="width: 200px;" placeholder="请选择地区" clearable filterable>
                    <el-option v-for="item in countryOptions" :key="item.label" :label="item.label"
                        :value="item.label" />
                </el-select>
            </div>
            <div class="filter-item">
                <span class="filter-label" style="font-size: 14px;min-width: 70px;">创建人：</span>
                <el-select v-model="filterParams.createUserId" placeholder="请选择创建人" style="width: 250px" clearable>
                    <el-option v-for="item in accountOptions" :key="item.id" :label="item.username" :value="item.id" />
                </el-select>
            </div>
            <div class="filter-item">
                <span class="filter-label" style="font-size: 14px;min-width: 70px;">创建时间：</span>
                <el-date-picker v-model="filterParams.createTime" style="width: 400px;" placeholder="请选择创建时间" clearable
                    type="datetimerange" start-placeholder="开始时间" end-placeholder="结束时间" format="YYYY-MM-DD HH:mm:ss"
                    date-format="YYYY/MM/DD ddd" time-format="A hh:mm:ss" />
            </div>
            <div class="filter-item">
                <el-button type="primary" :icon="Search" @click="handleSearch">查询</el-button>
            </div>
        </div>
        <div class="material-table">
            <div class="table-actions">
                <el-button type="primary" @click="handleSearch()"><el-icon>
                        <RefreshRight />
                    </el-icon> 刷新</el-button>
                <el-button type="primary" @click="handleCreate">素材识别编排</el-button>
                <el-button type="primary" @click="handleManualUpload">手动上传识别</el-button>
                <el-button type="primary" @click="handleBatchDownload" :loading="batchDownloadLoading">
                    <el-icon>
                        <Download />
                    </el-icon> 批量下载当前页
                </el-button>
                <el-button type="primary" @click="handleBatchDownloadSelected" :loading="batchDownloadLoading"
                    :disabled="selectedVideos.size === 0">
                    <el-icon>
                        <Download />
                    </el-icon> 批量下载已勾选 ({{ selectedVideos.size }})
                </el-button>
                <el-button type="warning" @click="clearAllSelected" v-if="selectedVideos.size > 0">
                    清空勾选
                </el-button>
            </div>
            <el-table :data="tableData" v-loading="loading" ref="tableRef" :expand-row-keys="expandedRows"
                :row-key="getRowKey" @expand-change="handleExpandChange"
                :header-cell-style="{ background: '#fafafa', height: '56px', }"
                style="width: 100%;margin-top: 20px;margin-bottom: 20px; height: calc(100% - 70px);">
                <el-table-column type="expand">
                    <template #default="props">
                        <div class="collapse-content-wrapper" @click.stop
                            v-if="props.row.detailRecordList && props.row.detailRecordList.length > 0">
                            <div class="expand-header">
                                <div style="display: flex; align-items: center; gap: 10px;">
                                    <el-checkbox :model-value="isAllSelectedInRow(props.row)"
                                        :indeterminate="isIndeterminate(props.row)"
                                        @change="(val: boolean) => handleSelectAllChange(props.row, val)" @click.stop>
                                        全选当前 ({{ getSelectedCountInRow(props.row) }}/{{
                                            props.row.detailRecordList.length }})
                                    </el-checkbox>
                                    <template v-if="props.row.isAuto">
                                        <span style="font-size: 14px; color: #666; margin-left: 20px;">排序：</span>
                                        <el-button :type="getExpandSort(props.row) === 'matchScore' ? 'primary' : 'default'"
                                            size="small" @click.stop="setExpandSort(props.row, 'matchScore')">
                                            匹配度 {{ getExpandSort(props.row) === 'matchScore' ?
                                                (getExpandSortOrder(props.row)
                                                    === 'desc' ? '↓' : '↑') : '' }}
                                        </el-button>
                                        <el-button :type="getExpandSort(props.row) === 'likeCount' ? 'primary' : 'default'"
                                            size="small" @click.stop="setExpandSort(props.row, 'likeCount')">
                                            点赞数 {{ getExpandSort(props.row) === 'likeCount' ?
                                                (getExpandSortOrder(props.row) ===
                                                    'desc' ? '↓' : '↑') : '' }}
                                        </el-button>
                                    </template>
                                </div>
                            </div>
                            <div class="material-grid">
                                <div v-for="(item, index) in getExpandPageItems(props.row)" :key="item.id || index"
                                    class="material-card" @click.stop="openMaterialDetail(item, props.row.isAuto)">
                                    <el-checkbox class="card-checkbox" :model-value="isVideoSelected(item)"
                                        @change="toggleVideoSelection(item)" @click.stop />
                                    <div class="card-image">
                                        <div class="video-placeholder" v-if="!isVideoLoaded(item.id)">
                                            <el-icon class="placeholder-icon">
                                                <VideoPlay />
                                            </el-icon>
                                        </div>
                                        <video class="video-thumbnail" preload="metadata" muted playsinline
                                            :src="item.downloadUrl" @loadeddata="onVideoLoaded(item.id)"
                                            :style="{ opacity: isVideoLoaded(item.id) ? 1 : 0 }"></video>
                                    </div>
                                    <div class="card-content">
                                        <div class="info-item" v-if="props.row.isAuto">
                                            <span class="label">匹配分数:</span>
                                            <span class="value">{{ item.matchScore }}</span>
                                        </div>
                                        <div class="info-item" v-if="props.row.isAuto">
                                            <span class="label">点赞数:</span>
                                            <span class="value">{{ item.likeCount }}</span>
                                        </div>
                                        <div class="info-item" v-if="props.row.isAuto">
                                            <span class="label">真人讲解:</span>
                                            <span class="value">{{ item.isRealPersonExplain ? '是' : '否' }}</span>
                                        </div>
                                        <div class="info-item">
                                            <span class="label">视频id:</span>
                                            <span class="value">{{ item?.videoId }}</span>
                                        </div>
                                        <div class="info-item">
                                            <span class="label">视频链接:</span>
                                            <span class="value link" @click.stop="openVideo(item.downloadUrl)">
                                                {{ item.downloadUrl }}</span>
                                        </div>
                                        <div class="info-item">
                                            <span class="label">视频描述:</span>
                                            <span class="value">{{ item.videoDescription || '无' }}</span>
                                        </div>
                                        <div class="info-item">
                                            <span class="label">任务状态:</span>
                                            <span class="value">
                                                {{ item.taskStatus == true ? '成功' : item.taskStatus == false ? '失败' : ''
                                                }}
                                            </span>
                                            <div v-if="item.taskStatus == false">
                                                <el-button type="danger" size="small"
                                                    @click.stop="retryTask(item, props.row.id)"><el-icon>
                                                        <RefreshRight />
                                                    </el-icon>重试</el-button>
                                            </div>
                                        </div>

                                    </div>
                                </div>
                            </div>
                            <div class="expand-pagination">
                                <el-pagination :current-page="getExpandPage(props.row)" :page-size="EXPAND_PAGE_SIZE"
                                    layout="prev, pager, next" :total="props.row.detailRecordList.length"
                                    @current-change="(p: number) => setExpandPage(props.row, p)" />
                            </div>
                        </div>
                        <div class="collapse-content-wrapper" @click.stop
                            style="display: flex;justify-content: center;align-items: center;padding: 40px 0;" v-else>
                            <span style="color: #909399;">No data</span>
                        </div>
                    </template>
                </el-table-column>
                <template v-for="(item, index) in tableHeader" :key="index">
                    <el-table-column :prop="item.prop" :label="item.label" :min-width="item.width"
                        :formatter="item.formatter">
                        <template #default="scope">
                        </template>
                    </el-table-column>
                </template>
            </el-table>
            <el-pagination v-model:current-page="pageNum" v-model:page-size="pageSize"
                style="display: flex;justify-content: end;" layout="total,prev, pager, next,sizes" :total="total"
                @size-change="handleSizeChange" @current-change="handleCurrentChange" />
        </div>

        <!-- 素材识别编排弹窗 -->
        <MaterialRecognitionDialog v-model:visible="dialogVisible" @success="handleSearch" ref="recognitionDialogRef" />

        <!-- 手动上传识别弹窗 -->
        <ManualUploadDialog v-model:visible="uploadDialogVisible" @success="handleSearch" ref="uploadDialogRef" />

        <!-- 素材详情弹窗 -->
        <MaterialDetailDialog v-model:visible="detailVisible" :material="currentMaterial" />
    </div>
</template>
<script setup lang="ts">
import { defineComponent, ref, reactive, onActivated } from 'vue';
import service from '../config';
import { RefreshRight, Search, VideoPlay, Download } from '@element-plus/icons-vue';
import { ElMessage, ElMessageBox, ElLoading } from 'element-plus';
import MaterialRecognitionDialog from '../components/MaterialRecognitionDialog.vue';
import MaterialDetailDialog from '../components/MaterialDetailDialog.vue';
import ManualUploadDialog from '../components/ManualUploadDialog.vue';
import { countryOptions } from '../tool';
import dayjs from 'dayjs'
import axios from 'axios';
import { useAuthStore } from '../store/auth';
import JSZip from 'jszip';

const authStore = useAuthStore()

defineComponent({ name: 'MaterialRecognition' })
const loading = ref(false)
const tableData = ref([])
const pageNum = ref(1)
const pageSize = ref(10)
const total = ref(0)

// 筛选参数
const filterParams = reactive({
    keyword: '',
    area: '',
    createTime: '',
    createUserId: ''
})

const tableHeader = ref([
    { label: '关键词', prop: 'keyword', width: 200, formatter: (row: any) => row.keyword?.length > 0 ? row.keyword : dayjs(row?.createTime).format('YYYY-MM-DD HH:mm:ss') },
    { label: '地区', prop: 'area', width: 150, formatter: (row: any) => row.area?.length > 0 ? row.area : '本地' },
    { label: '出词数', prop: 'wordNum', width: 150, formatter: (row: any) => row.wordNum ? row.wordNum : 1 },
    { label: '识别结果数', prop: 'count', width: 150, formatter: (row: any) => row.detailRecordList ? row.detailRecordList.length : 0 },
    { label: '创建人', prop: 'createUserId',width: 250,  formatter: (row: any) => accountOptions.value.find(item => item.id == row.createUserId)?.username || '' },
    { label: '素材类型', prop: 'isAuto', width: 100, formatter: (row: any) => row.isAuto ? '自动' : '手动' },
    { label: '创建时间', prop: 'createTime', width: 160, formatter: (row: any) => dayjs(row?.createTime).format('YYYY-MM-DD HH:mm:ss') },
])

const accountOptions = ref([])
const getAccount = () => {
    service.get('/user/getAll')
        .then(response => {
            accountOptions.value = response?.data
        })
        .catch(error => {
            ElMessage.error(error)
        });
}

//#region 展开区域数据
const tableRef = ref()
const expandedRows = ref<string[]>([])

// 展开区分页
const EXPAND_PAGE_SIZE = 12
const expandPageMap = ref<Record<string, number>>({})
const expandSortMap = ref<Record<string, { field: 'matchScore' | 'likeCount' | null, order: 'asc' | 'desc' }>>({})// 展开区排序
const selectedVideos = ref<Map<string, any>>(new Map()) //视频选择

const getRowKey = (row: any) => String(row.id ?? row.keyword ?? Math.random())

// 处理展开行变化
const handleExpandChange = (row: any, expandedRowsData: any[]) => {
    const rowKey = getRowKey(row)
    const isExpanded = expandedRowsData.some(r => getRowKey(r) === rowKey)
    if (isExpanded) {
        if (!expandedRows.value.includes(rowKey)) {
            expandedRows.value.push(rowKey)
        }
    } else {
        const index = expandedRows.value.indexOf(rowKey)
        if (index > -1) {
            expandedRows.value.splice(index, 1)
        }
    }
}

const getExpandPage = (row: any) => expandPageMap.value[getRowKey(row)] || 1
const setExpandPage = (row: any, page: number) => {
    expandPageMap.value[getRowKey(row)] = page
}

//排序
const getExpandSort = (row: any) => {
    const key = getRowKey(row)
    return expandSortMap.value[key]?.field || null
}
//排序方向
const getExpandSortOrder = (row: any) => {
    const key = getRowKey(row)
    return expandSortMap.value[key]?.order || 'desc'
}

const setExpandSort = (row: any, field: 'matchScore' | 'likeCount') => {
    const key = getRowKey(row)
    const current = expandSortMap.value[key]
    if (current?.field === field) {
        expandSortMap.value[key] = {
            field,
            order: current.order === 'desc' ? 'asc' : 'desc'
        }
    } else {
        expandSortMap.value[key] = {
            field,
            order: 'desc'
        }
    }
    setExpandPage(row, 1)
}

const getExpandPageItems = (row: any) => {
    let list = [...(row.detailRecordList || [])]
    const key = getRowKey(row)
    const sort = expandSortMap.value[key] // 排序
    if (sort?.field) {
        list.sort((a, b) => {
            const aVal = Number(a[sort.field]) || 0
            const bVal = Number(b[sort.field]) || 0
            return sort.order === 'desc' ? bVal - aVal : aVal - bVal
        })
    }

    // 分页
    const page = getExpandPage(row)
    const start = (page - 1) * EXPAND_PAGE_SIZE
    return list.slice(start, start + EXPAND_PAGE_SIZE)
}
//#endregion

// 视频加载状态管理
const videoLoadedMap = ref<Record<string, boolean>>({})
const isVideoLoaded = (videoId: number) => {
    return videoLoadedMap.value[videoId] || false
}
const onVideoLoaded = (videoId: number) => {
    videoLoadedMap.value[videoId] = true
}

//#region 视频勾选相关
const getVideoKey = (video: any) => {
    return String(video.id || video.downloadUrl || video.videoId)
}

// 判断视频是否被选中
const isVideoSelected = (video: any) => {
    return selectedVideos.value.has(getVideoKey(video))
}

// 切换单个视频选择状态
const toggleVideoSelection = (video: any) => {
    const key = getVideoKey(video)
    if (selectedVideos.value.has(key)) {
        selectedVideos.value.delete(key)
    } else {
        // 存储完整的视频信息
        selectedVideos.value.set(key, {
            url: video.downloadUrl,
            fileName: video.videoId ? `${video.videoId}.mp4` : `video_${Date.now()}.mp4`,
            videoId: video.videoId,
            videoData: video
        })
    }
    // 触发响应式更新
    selectedVideos.value = new Map(selectedVideos.value)
}

// 判断某一行是否全选
const isAllSelectedInRow = (row: any) => {
    if (!row.detailRecordList || row.detailRecordList.length === 0) return false
    return row.detailRecordList.every((item: any) => isVideoSelected(item))
}

//部分选中
const isIndeterminate = (row: any) => {
    const selectedCount = getSelectedCountInRow(row)
    const totalCount = row.detailRecordList?.length || 0
    return selectedCount > 0 && selectedCount < totalCount
}

// 获取某一行已选中的数量
const getSelectedCountInRow = (row: any) => {
    if (!row.detailRecordList || row.detailRecordList.length === 0) return 0
    return row.detailRecordList.filter((item: any) => isVideoSelected(item)).length
}

const handleSelectAllChange = (row: any, checked: boolean) => {
    if (!row.detailRecordList || row.detailRecordList.length === 0) return
    
    row.detailRecordList.forEach((item: any) => {
        const key = getVideoKey(item)
        if (checked) {
            selectedVideos.value.set(key, {
                url: item.downloadUrl,
                fileName: item.videoId ? `${item.videoId}.mp4` : `video_${Date.now()}.mp4`,
                videoId: item.videoId,
                videoData: item
            })
        } else {
            selectedVideos.value.delete(key)
        }
    })
    // 触发响应式更新
    selectedVideos.value = new Map(selectedVideos.value)
}

// 清空所有勾选
const clearAllSelected = () => {
    selectedVideos.value.clear()
    selectedVideos.value = new Map(selectedVideos.value)
}
//#endregion

// 查询数据
const handleSearch = () => {
    loading.value = true

    // 处理时间参数
    let createTimeArray = null
    if (filterParams.createTime && Array.isArray(filterParams.createTime) && filterParams.createTime.length === 2) {
        createTimeArray = [
            dayjs(filterParams.createTime[0]).format('YYYY-MM-DD HH:mm:ss'),
            dayjs(filterParams.createTime[1]).format('YYYY-MM-DD HH:mm:ss')
        ]
    }

    service.post('/materialRecord/page', {
        keyword: filterParams.keyword,
        area: filterParams.area,
        createUserId: filterParams.createUserId,
        createTime: createTimeArray,
        pageNum: pageNum.value,
        pageSize: pageSize.value
    })
        .then(response => {
            tableData.value = response.data?.records || []
            total.value = response.data?.total || 0
        })
        .catch(error => {
            ElMessage.error(error?.message || '查询失败')
        }).finally(() => {
            loading.value = false
        })
}

// 分页处理
const handleSizeChange = () => {
    pageNum.value = 1
    handleSearch()
}

const handleCurrentChange = () => {
    handleSearch()
}

// 识别编排弹窗
const dialogVisible = ref(false)
const recognitionDialogRef = ref()

const handleCreate = () => {
    recognitionDialogRef.value?.resetForm()
    dialogVisible.value = true
}

// 手动上传识别弹窗
const uploadDialogVisible = ref(false)
const uploadDialogRef = ref()

const handleManualUpload = () => {
    uploadDialogRef.value?.resetForm()
    uploadDialogVisible.value = true
}

// 打开视频链接
const openVideo = (url: string) => {
    if (url) {
        window.open(url, '_blank')
    }
}

// 物料详情弹窗
const detailVisible = ref(false)
const currentMaterial = ref<any>(null)
const openMaterialDetail = (row: any, isAuto: boolean) => {
    currentMaterial.value = row
    currentMaterial.value.isAuto = isAuto || false
    detailVisible.value = true
}

// 重试任务
const retryTask = async (item: any, id: string) => {
    try {
        let webhookUrl = import.meta.env.PROD
            ? 'https://pixeljet-n8n.com/webhook/61e8b870-a088-484d-bf7e-f718b67410fe'
            : '/wkfapi/webhook/61e8b870-a088-484d-bf7e-f718b67410fe'
        const payload: any = {
            url: item.downloadUrl,
            arrange_id: id,
            created_user_id: authStore?.userId,
            id: item.id,
            action: "update",
            model: item.model
        }
        if (import.meta.env.MODE !== 'production') {
            payload.devModel = 'test'
        } else {
            payload.devModel = 'official'
        }
        await axios.post(webhookUrl, payload)
        ElMessage.success('任务已重试')
    }
    catch (error) {
        ElMessage.error('任务重试失败')
    }

}

//#region 批量下载
const batchDownloadLoading = ref(false)
const executeBatchDownload = async (videos: any[], zipFileName: string, onComplete?: () => void) => {
    if (videos.length === 0) {
        return
    }
    batchDownloadLoading.value = true
    const loadingInstance = ElLoading.service({
        lock: true,
        text: `正在下载视频 0/${videos.length}...`,
        background: 'rgba(0, 0, 0, 0.7)',
    })
    const zip = new JSZip()
    let successCount = 0
    let failCount = 0
    const failedVideos: Array<{ url: string; fileName: string; videoId?: string; error: string }> = []
    
    try {
        for (let i = 0; i < videos.length; i++) {
            const video = videos[i]
            try {
                const progressText = failCount > 0 
                    ? `正在下载视频 ${i + 1}/${videos.length}...\n${video.fileName}\n已失败: ${failCount} 个`
                    : `正在下载视频 ${i + 1}/${videos.length}...\n${video.fileName}`
                loadingInstance.setText(progressText)
                
                const response = await axios.get(video.url, {
                    responseType: 'blob',
                    timeout: 180000
                })
                const blob = new Blob([response.data], { type: 'video/mp4' })
                const fileName = `${i + 1}_${video.fileName}`
                zip.file(fileName, blob)
                successCount++
            } catch (error: any) {
                console.error(`下载失败: ${video.fileName}`, error)
                failCount++
                const errorMessage = error?.response?.status 
                    ? `HTTP ${error.response.status}: ${error.response.statusText || '请求失败'}`
                    : error?.message || '网络错误或超时'
                
                failedVideos.push({
                    url: video.url,
                    fileName: video.fileName,
                    videoId: video.videoId,
                    error: errorMessage
                })
            }
        }

        if (successCount === 0) {
            loadingInstance.close()
            const failedListHtml = failedVideos.map((item, index) => 
                `<div style="margin: 8px 0; padding: 8px; background: #fff2f0; border-left: 3px solid #ff4d4f; border-radius: 4px;">
                    <div style="font-weight: 500; color: #333; margin-bottom: 4px;">${index + 1}. ${item.fileName}</div>
                    <div style="font-size: 12px; color: #999;">错误: ${item.error}</div>
                </div>`
            ).join('')
            
            try {
                await ElMessageBox.confirm(
                    `<div style="max-height: 400px; overflow-y: auto; width: 360px;">
                        <p style="margin-bottom: 12px; color: #ff4d4f; font-weight: 500;">所有视频下载失败，共 ${failCount} 个文件：</p>
                        ${failedListHtml}
                    </div>`,
                    '下载失败',
                    {
                        dangerouslyUseHTMLString: true,
                        confirmButtonText: '重新下载',
                        cancelButtonText: '取消',
                        type: 'error',
                        customStyle: { width: '500px' },
                        distinguishCancelAndClose: true
                    }
                )
                // 重新下载失败文件
                batchDownloadLoading.value = false
                const retryVideos = failedVideos.map(item => ({
                    url: item.url,
                    fileName: item.fileName,
                    videoId: item.videoId
                }))
                const retryZipFileName = `下载视频_重试_${dayjs().format('YYYY-MM-DD_HH-mm-ss')}.zip`
                await executeBatchDownload(retryVideos, retryZipFileName, onComplete)
                return
            } catch {
                // 用户点击了"取消"或关闭按钮
                batchDownloadLoading.value = false
                return
            }
        }

        // 生成 ZIP 文件
        loadingInstance.setText(`正在打包 ${successCount} 个视频... 0%`)
        const zipBlob = await zip.generateAsync(
            {
                type: 'blob',
                compression: 'DEFLATE',
                compressionOptions: { level: 6 }
            },
            (metadata) => {
                const percent = Math.round(metadata.percent)
                loadingInstance.setText(`正在打包 ${successCount} 个视频... ${percent}%`)
            }
        )

        // 下载 ZIP 文件
        loadingInstance.setText('正在保存文件...')
        const blobUrl = window.URL.createObjectURL(zipBlob)
        const link = document.createElement('a')
        link.href = blobUrl
        link.download = zipFileName
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
        window.URL.revokeObjectURL(blobUrl)

        loadingInstance.close()
        
        // 处理有失败文件情况
        if (failCount > 0) {
            const failedListHtml = failedVideos.map((item, index) => 
                `<div style="margin: 8px 0; padding: 8px; background: #fff7e6; border-left: 3px solid #faad14; border-radius: 4px;">
                    <div style="font-weight: 500; color: #333; margin-bottom: 4px;">${index + 1}. ${item.fileName}</div>
                    <div style="font-size: 12px; color: #999;">错误: ${item.error}</div>
                </div>`
            ).join('')
            
            ElMessage.success({
                message: `批量下载完成！成功: ${successCount} 个，失败: ${failCount} 个`,
                duration: 3000,
                showClose: true,
            })
            
            setTimeout(async () => {
                try {
                    await ElMessageBox.confirm(
                        `<div style="max-height: 400px; overflow-y: auto;width: 360px;">
                            <p style="margin-bottom: 12px; color: #faad14; font-weight: 500;">以下 ${failCount} 个文件下载失败：</p>
                            ${failedListHtml}
                            <p style="margin-top: 12px; color: #666; font-size: 12px;">成功的 ${successCount} 个文件已打包在 ZIP 中。</p>
                        </div>`,
                        '部分文件下载失败',
                        {
                            dangerouslyUseHTMLString: true,
                            confirmButtonText: '重新下载失败文件',
                            cancelButtonText: '我知道了',
                            type: 'warning',
                            customStyle: { width: '500px' },
                            distinguishCancelAndClose: true
                        }
                    )
                    // 重新下载失败文件
                    const retryVideos = failedVideos.map(item => ({
                        url: item.url,
                        fileName: item.fileName,
                        videoId: item.videoId
                    }))
                    const retryZipFileName = `下载视频_重试失败_${dayjs().format('YYYY-MM-DD_HH-mm-ss')}.zip`
                    await executeBatchDownload(retryVideos, retryZipFileName, onComplete)
                } catch {
                   
                }
            }, 500)
        } else {
            ElMessage.success(`批量下载完成！成功下载 ${successCount} 个视频`)
        }
        
        // 执行完成回调
        if (onComplete) {
            onComplete()
        }
    } catch (error) {
        console.error('批量下载失败:', error)
        loadingInstance.close()
        ElMessage.error('批量下载失败，请重试')
    } finally {
        batchDownloadLoading.value = false
    }
}

// 批量下载当前页所有视频
const handleBatchDownload = async () => {
    // 收集当前页所有视频
    const allVideos: any[] = []
    tableData.value.forEach((row: any) => {
        if (row.detailRecordList && row.detailRecordList.length > 0) {
            row.detailRecordList.forEach((item: any) => {
                if (item.downloadUrl) {
                    allVideos.push({
                        url: item.downloadUrl,
                        fileName: item.videoId ? `${item.videoId}.mp4` : `video_${Date.now()}.mp4`,
                        videoId: item.videoId
                    })
                }
            })
        }
    })
    if (allVideos.length === 0) {
        ElMessage.warning('当前页没有可下载的视频')
        return
    }
    try {
        await ElMessageBox.confirm(
            `检测到 ${allVideos.length} 个视频，将打包成 ZIP 文件下载，是否继续？`,
            '批量下载确认',
            {
                confirmButtonText: '确定下载',
                cancelButtonText: '取消',
                type: 'info',
            }
        )
    } catch {
        return
    }
    const zipFileName = `下载视频_${dayjs().format('YYYY-MM-DD_HH-mm-ss')}.zip`
    await executeBatchDownload(allVideos, zipFileName)
}

// 批量下载已勾选的视频
const handleBatchDownloadSelected = async () => {
    const allVideos: any[] = Array.from(selectedVideos.value.values()).filter(v => v.url)
    
    if (allVideos.length === 0) {
        ElMessage.warning('请先勾选要下载的视频')
        return
    }
    try {
        await ElMessageBox.confirm(
            `即将下载 ${allVideos.length} 个已勾选的视频，将打包成 ZIP 文件下载，是否继续？`,
            '批量下载确认',
            {
                confirmButtonText: '确定下载',
                cancelButtonText: '取消',
                type: 'info',
            }
        )
    } catch {
        return
    }
    const zipFileName = `下载视频_${dayjs().format('YYYY-MM-DD_HH-mm-ss')}.zip`
    await executeBatchDownload(allVideos, zipFileName, () => {
        clearAllSelected()
    })
}
//#endregion

onActivated(() => {
    getAccount()
    handleSearch()
})


</script>
<style lang="scss" scoped>
.material-page {
    background-color: #fff;
    height: calc(100% - 10px);
    padding: 30px;
    width: 100%;
    box-sizing: border-box;

    .title {
        font-size: 20px;
        font-weight: 600;
    }

    .fliter {
        display: flex;
        align-items: center;
        margin: 30px 0;
        flex-wrap: wrap;
        gap: 10px 12px;

        .filter-item {
            display: inline-flex;
            align-items: center;
            gap: 8px;
        }
    }

    .material-table {
        margin-top: 20px;
        height: calc(100% - 180px);

        .table-actions {
            display: flex;
            gap: 10px;
            margin-bottom: 20px;
        }
    }

    .el-button--primary {
        background-color: #1677ff;
    }

    .el-table__row {
        font-size: 13px;
    }
}

// 展开内容样式
.collapse-content-wrapper {
    padding: 20px;
}

.expand-header {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 16px;
}

.material-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
    gap: 16px;
    max-height: 600px;
    overflow-y: auto;
}

.expand-pagination {
    display: flex;
    justify-content: center;
    margin-top: 12px;
}

.material-card {
    border: 1px solid #e8e8e8;
    background: white;
    border-radius: 8px;
    padding: 12px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    transition: box-shadow 0.3s ease;
    display: flex;
    position: relative;
    align-items: center;
    &:hover {
        box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
    }

    .card-checkbox {
        position: absolute;
        top: 4px;
        right: 8px;
        z-index: 10;
        background: rgba(255, 255, 255, 0.9);
        border-radius: 4px;
        padding: 2px;
    }
}

.card-image {
    width: 80px;
    flex-shrink: 0;
    margin-bottom: 0;
    border-radius: 4px;
    overflow: hidden;
    position: relative;

    .video-placeholder {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
        z-index: 1;

        .placeholder-icon {
            font-size: 24px;
            color: #999;
        }
    }

    .video-thumbnail {
        width: 100%;
        height: 100%;
        display: block;
        z-index: 2;
    }
}


.card-content {
    flex: 1;
    margin-left: 10px;
    min-width: 0px;

    .info-item {
        display: flex;
        margin-bottom: 4px;
        font-size: 12px;
        line-height: 1.4;

        .label {
            width: 60px;
            color: #666;
            font-weight: 500;
        }

        .value {
            flex: 1;
            color: #333;
            word-break: break-all;
            overflow: hidden;
            white-space: nowrap;
            text-overflow: ellipsis;
            display: inline-block;
            min-width: 0;

            &.link {
                color: #1677ff;
                cursor: pointer;
                text-decoration: underline;

                &:hover {
                    color: #4096ff;
                }
            }
        }
    }
}
</style>